package org.liaohailong.library.widget.photoview.guesture;

import android.graphics.PointF;
import android.util.Log;
import android.view.MotionEvent;

import androidx.annotation.NonNull;

/**
 * create by liaohailong
 * time 2023/1/9 11:05
 * desc: 旋转操作手势监听
 */
public class RotateGestureDetector {

    private static final int MAX_DEGREES_STEP = 120;

    private void log(@NonNull String format, Object... args) {
        String msg = String.format(format, args);
        Log.i("RotateGestureDetector", msg);
    }

    private Callback callback;

    public void setCallback(Callback callback) {
        this.callback = callback;
    }


    private final PointF midPoint = new PointF();
    private float lastDegrees = 0.0f;


    public void onTouchEvent(@NonNull MotionEvent event) {
        /*
         * 实现逻辑：
         * 1，当用户多指按下时，仅为两指，记录两指位置
         * 2，ACTION_MOVE事件，持续计算角度，当前移动的两点与最开始记录的两点
         * 3，角度计算：同位角 + 角互补 推算出旋转角度=当前直线左下角的角度 - 最开始直线左下角的角度
         * 4，tan值 -> 弧度 -> 角度
         *
         * */
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_POINTER_DOWN: {
                int actionIndex = event.getActionIndex();
                log("ACTION_POINTER_DOWN actionIndex: %s", actionIndex);
                // 当前角度
                lastDegrees = calcDegrees(event);
            }
            break;
            case MotionEvent.ACTION_POINTER_UP: {
                int actionIndex = event.getActionIndex();
                log("ACTION_POINTER_UP actionIndex: %s", actionIndex);
            }

            case MotionEvent.ACTION_MOVE: {
                int pointerCount = event.getPointerCount();
                if (pointerCount >= 2) {
                    // 移动过程中当前角度
                    float currDegrees = calcDegrees(event);
                    // 记录中点
                    getMidPointF(midPoint, event);

                    float rotateDeg = currDegrees - lastDegrees;
//                    log("rotateDeg: %s, centerX: %s, centerY: %s", rotateDeg, midPoint.x, midPoint.y);

                    // 返回旋转角度，旋转中心坐标
                    if (Math.abs(rotateDeg) <= MAX_DEGREES_STEP) {
                        // MAX_DEGREES_STEP 处理一下特殊情况，理论上三角函数计算方法，是要求角度不超过180度的
                        if (callback != null) {
                            callback.onRotate(rotateDeg, midPoint.x, midPoint.y);
                        }
                    }

                    lastDegrees = currDegrees;
                }
            }
            break;
        }
    }


    private float calcDegrees(@NonNull MotionEvent event) {
        float x0 = event.getX(0);
        float y0 = event.getY(0);
        float x1 = event.getX(1);
        float y1 = event.getY(1);
        // 计算反正切值
        float aTan = (y1 - y0) / (x1 - x0);
        // 反正切值 -> 弧度值 -> 角度值
        return (float) Math.toDegrees(Math.atan(aTan));
    }

    private void getMidPointF(@NonNull PointF midPoint, @NonNull MotionEvent event) {
        float x0 = event.getX(0);
        float y0 = event.getY(0);
        float x1 = event.getX(1);
        float y1 = event.getY(1);

        float cx = (x0 + x1) / 2;
        float cy = (y0 + y1) / 2;
        midPoint.set(cx, cy);
    }


    public interface Callback {
        /**
         * 旋转操作触发回调
         *
         * @param rotateDeg 基于手机屏幕坐标系，每次ACTION_MOVE事件造成的旋转角度
         * @param cx         旋转中心点x坐标，以第一次两指按下时形成的线为基准
         * @param cy         旋转中心点y坐标，以第一次两指按下时形成的线为基准
         */
        void onRotate(float rotateDeg, float cx, float cy);
    }


}
